package com.dahua.messageconsumer;

import com.alibaba.fastjson.JSON;
import com.dahua.common.config.LatestSensorStatusData;
import com.dahua.common.config.PublicVars;
import com.dahua.common.config.PublicVarsTimeDay;
import com.dahua.common.dao.*;
import com.dahua.common.domain.*;
import com.dahua.common.service.*;
import com.dahua.messageconsumer.model.EmailData;
import com.dahua.messageconsumer.model.EmailDatalList;
import com.dahua.messageconsumer.service.ActiveMqConfig;
import com.dahua.messageconsumer.service.MyWebSocketClient;
import com.dahua.messageconsumer.sql.QueueTimes;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.jms.*;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.ContainerProvider;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

@Configuration
@EnableScheduling
@Slf4j
public class SchedulingConfig implements SchedulingConfigurer {
    private ConfigsDao configsDao;
    private SensorService sensorService;
    private EquipmentData4CheckMapper equipmentData4CheckMapper;
    private SensorDataMapper sensorDataMapper;
    private SyncMessageMapper syncMessageMapper;
    private RuntimeParamMapper runtimeParamMapper;
    private LatestSensorStatusMapper latestSensorStatusMapper;
    private Control56wbMapper control56wbMapper;
    private EquipmentMapper equipmentMapper;
    private ConsumeenergyMapper consumeenergyMapper;
    private ConsumeenergystationMapper consumeenergystationMapper;
    private ActiveMqConfig activeMqConfig;
    private Control56Mapper control56Mapper;
    private DictDetailMapper dictDetailMapper;
    private EquipmentStatusThisMonthMapper equipmentStatusThisMonthMapper;
    private EquipmentStatusTodayMapper equipmentStatusTodayMapper;
    private EquipmentStatusAlldayMapper equipmentStatusAlldayMapper;

    private int totalCount = 360;  // 1小时
    // private int totalCount = 30; // 测试，5分钟
    private int count = 0;
    private int yyyymmdd = 0;

    private int count4SyncMessage = 0;
    private int totalCount4SyncMessage = 12; // 2分钟
    private Timestamp dateTime4SyncMessage = Timestamp.valueOf(LocalDateTime.now());

    // public static volatile ConcurrentLinkedDeque<Consumeenergy> energyQueue = new ConcurrentLinkedDeque<>();

    @Value("${data.filesystem}")
    private String filesystem;
    // isreceiver = 1: 只接收，送队列 ； 0：正常处理 --> 不再使用这个方案了。
    //    @Value("${data.isreceiver}")
    //    private Integer isreceiver;

    @Value("${data.websocket1}")
    private String websocket1;
    // 如果是线路线网合一。这个websocket2就指向portal
    @Value("${data.websocket2}")
    private String websocket2;
    // 如果是线路线网合一。这个websocket3就指向portal
    @Value("${data.websocket3}")
    private String websocket3;

    @Value("${data.saveenergy}")
    private Integer saveenergy; // 根据电流计算能耗

    public final String QUEUE_ENERGY = "energy";

    Session[] sessions = new Session[3];

    ConnectionFactory connectionFactory = null;
    Connection connection = null;
    javax.jms.Session session = null;
    javax.jms.MessageConsumer messageConsumer = null;

    @Value("${data.sqltrytimes}")
    private Integer sqltrytimes;

    public static volatile int saveTimeCount = 0;

    @Autowired
    public SchedulingConfig(
            ConfigsDao configsDao,
            SensorService sensorService,
            EquipmentData4CheckMapper equipmentData4CheckMapper,
            SensorDataMapper sensorDataMapper,
            SyncMessageMapper syncMessageMapper,
            RuntimeParamMapper runtimeParamMapper,
            LatestSensorStatusMapper latestSensorStatusMapper,
            Control56wbMapper control56wbMapper,
            EquipmentMapper equipmentMapper,
            ConsumeenergyMapper consumeenergyMapper,
            ConsumeenergystationMapper consumeenergystationMapper,
            ActiveMqConfig activeMqConfig,
            Control56Mapper control56Mapper,
            DictDetailMapper dictDetailMapper,
            EquipmentStatusThisMonthMapper equipmentStatusThisMonthMapper,
            EquipmentStatusTodayMapper equipmentStatusTodayMapper,
            EquipmentStatusAlldayMapper equipmentStatusAlldayMapper
    ) {
        this.configsDao = configsDao;
        this.sensorService = sensorService;
        this.equipmentData4CheckMapper = equipmentData4CheckMapper;
        this.sensorDataMapper = sensorDataMapper;
        this.syncMessageMapper = syncMessageMapper;
        this.runtimeParamMapper = runtimeParamMapper;
        this.latestSensorStatusMapper = latestSensorStatusMapper;
        this.control56wbMapper = control56wbMapper;
        this.equipmentMapper = equipmentMapper;
        this.consumeenergyMapper = consumeenergyMapper;
        this.consumeenergystationMapper = consumeenergystationMapper;
        this.activeMqConfig = activeMqConfig;
        this.control56Mapper = control56Mapper;
        this.dictDetailMapper = dictDetailMapper;
        this.equipmentStatusThisMonthMapper = equipmentStatusThisMonthMapper;
        this.equipmentStatusTodayMapper = equipmentStatusTodayMapper;
        this.equipmentStatusAlldayMapper = equipmentStatusAlldayMapper;
    }

    @PostConstruct
    public void checkFileSystem() {
        if (filesystem == null || filesystem.isEmpty()) {
            filesystem = "/data";
        }
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(12));
    }

    @Scheduled(initialDelay = 3000, fixedDelay = 10000)
    public void Init() {
        if (!PublicVars.hasApplicationInit) {
            log.info("读取数据库参数&sensors失败 ! " + LocalDateTime.now());
            MessageConsumer.sensors = sensorService.getAllSensor();
            if (MessageConsumer.sensors == null || MessageConsumer.sensors.isEmpty()) {
                return;
            }

            List<Configs> configs = configsDao.getConfigs();
            if (configs == null || configs.isEmpty()) {
                return;
            }
            PublicVars.loadEvelatorConfigsFromDict(dictDetailMapper);
            if (PublicVars.elevatorStatusConfigs == null || PublicVars.elevatorStatusConfigs.isEmpty()) {
                return;
            }

            PublicVars.hasApplicationInit = PublicVars.initParmsFromDB(configs);
            if (PublicVars.hasApplicationInit) {
                log.info("读取数据库参数&sensors成功 ! " + LocalDateTime.now());
                yyyymmdd = LocalDateTime.now().getYear()*10000 + LocalDateTime.now().getMonthValue()*100 + LocalDateTime.now().getDayOfMonth();
            }
            PublicVars.needDailyInit = false;
            PublicVars.needReadConfigs = false;
            PublicVars.needReadDicts = false;
            return;
        }
        // 曾经发生过初始化导致某个维保动作没有保存,所以将这两个独立出来
        if (PublicVars.needDailyInit) {
            log.warn("doing daily init......");
            PublicVars.clearallmap();
            LatestSensorStatusData.clearMap();
            MessageConsumer.sensors = sensorService.getAllSensor();
            if (MessageConsumer.sensors == null || MessageConsumer.sensors.isEmpty()) {
                return;
            }
            PublicVars.needDailyInit = false;
            yyyymmdd = LocalDateTime.now().getYear()*10000 + LocalDateTime.now().getMonthValue()*100 + LocalDateTime.now().getDayOfMonth();
        }
        if (PublicVars.needReadConfigs) {
            log.warn("reading configs......");
            List<Configs> configs = configsDao.getConfigs();
            if (configs == null || configs.isEmpty()) {
                return;
            }
            PublicVars.initParmsFromDB(configs);

            PublicVars.needReadConfigs = false;
        }
        if (PublicVars.needReadDicts) {
            log.warn("reading dicts......");
            PublicVars.loadEvelatorConfigsFromDict(dictDetailMapper);
//            if (PublicVars.elevatorStatusConfigs == null || PublicVars.elevatorStatusConfigs.isEmpty()) {
//                return;
//            }

            PublicVars.needReadDicts = false;
        }

        // 及时清理缓存 : 2 mins
        count4SyncMessage++;
        if (count4SyncMessage >= totalCount4SyncMessage) {
            count4SyncMessage = 0;
            dateTime4SyncMessage = PublicVars.flushCache(syncMessageMapper, dateTime4SyncMessage);

            // PublicVars.loadEvelatorConfigsFromDict(dictDetailMapper);

        }

        // 定时重读取
        count++;
        if (count >= totalCount) {   // 360 * 10 s = 1 hour
            // 主动删除不完整的数据
            deleteSensorData();

            count = 0;
            // 02：00到03：00之间重新初始化
            int hour = LocalDateTime.now().getHour();
            // 测试 if (hour >= 18 && hour < 20) {
            if (hour >= 2 && hour < 8) {
                // 只要有维保未结束的不能初始化
                if (MessageConsumer.isMaintainenceStatus == null || MessageConsumer.isMaintainenceStatus.isEmpty()) {
                    int yyyymmdd0 = LocalDateTime.now().getYear() * 10000 + LocalDateTime.now().getMonthValue() * 100 + LocalDateTime.now().getDayOfMonth();
                    // 每天只读取一次
                    if (yyyymmdd0 != yyyymmdd) {
                        // PublicVars.clearallmap();
                        // PublicVars.hasApplicationInit = false;
                        PublicVars.needDailyInit = true;
                        PublicVars.needReadConfigs = true;
                        PublicVars.needReadDicts = true;
                    }
                }
            }
        }
    }

    @Scheduled(initialDelay = 10000, fixedDelay = 3000)
    public void getAllRuntimeParams() {

        if (!PublicVars.hasApplicationInit) {
            return;
        }

        // 数据给工控机用。独立的线网服务器不需要执行
        if (PublicVars.isIndependentNetworkServer == 1) {
            return;
        }

        //PublicVars.runtimeParams.clear();
        PublicVars.runtimeParams = runtimeParamMapper.getValidFtpAllFilesParamList();
    }

    private void deleteSensorData() {
        LocalDateTime maketime = LocalDateTime.now().minusMinutes(60L);
        List<EquipmentData4Check> equipmentData4Checks = equipmentData4CheckMapper.getAllEquipmentData4ChecksBefore60mins(maketime);

        if (equipmentData4Checks != null && !equipmentData4Checks.isEmpty()) {
            for (EquipmentData4Check item : equipmentData4Checks) {
                for (Sensor sensor : MessageConsumer.sensors) {
                    if ("A".equalsIgnoreCase(sensor.getSensor_type()) == false)
                        continue;

                    try {
                        sensorDataMapper.deleteByEqidAndTime(item.getEquipmentid(), sensor.getID(), item.getDatatime());
                    } catch (Exception e2) {
                        log.error(e2.getMessage());
                    }
                }
                equipmentData4CheckMapper.deleteByEquipmentidMaketime(item.getEquipmentid(),item.getMaketime());
            }
        }
    }

    public static boolean isLinux() {
        return System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0;
    }
    @Scheduled(initialDelay = 10000, fixedDelay = 3600000)
    public void getDiskUsage() {
        if (!isLinux()) {
            MessageConsumer.diskUsageInfo = " not linux system";
            return;
        }
        String ret = null;
        String ret2 = null;
        try {
            Runtime rt = Runtime.getRuntime();
            String command = "df -hl " + filesystem; // df -hl  /data 查看硬盘空间
            Process p = rt.exec(command);
            BufferedReader in = null;
            try {
                in = new BufferedReader(new InputStreamReader(
                        p.getInputStream()));
                String[] strArray = null;
                while ((ret2 = in.readLine()) != null) {
                    ret = ret2;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (ret == null)
            ret = "";
        String portal = getPortalDiskUsage();
        MessageConsumer.diskUsageInfo =  "line: " + ret + LocalDateTime.now().toString()
                + ", " + portal;
    }

    private String getPortalDiskUsage() {
        if (PublicVars.isPortalWithData == 1) {
            return "";
        }

        try {
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setConnectTimeout(30000); //设置超时
            requestFactory.setReadTimeout(60000);
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            //RestTemplate restTemplate = new RestTemplate();
            String url = PublicVars.centralPortalApiBaseUrl + "/portal/diskusage";
            return restTemplate.getForObject(url, String.class);
        } catch (Exception ex) {
            return "error";
        }
    }

    @Scheduled(initialDelay = 5000, fixedDelay = 1000)
    public void send2WebSocket1() {
        send2WebSocket(MessageConsumer.wsTime, 0, websocket1);
    }
    // 线路线网合一情况下，需要同时发给 web / portal
    @Scheduled(initialDelay = 5000, fixedDelay = 1000)
    public void send2WebSocket2() {
        send2WebSocket(MessageConsumer.wsTime2, 1, websocket2);
    }
    // 线路线网合一情况下，内网故障转发，统一从portal
    @Scheduled(initialDelay = 5000, fixedDelay = 1000)
    public void send2WebSocket_Fault2Email() {
        send2WebSocket_Fault2Email(MessageConsumer.wsTime2, 2, websocket3);
    }

    public void send2WebSocket(LocalDateTime wsTime, int sessionIndex, String websocket) {
        if (websocket == null || websocket.isEmpty()) {
            return;
        }
        wsTime = LocalDateTime.now();

        if (sessions[sessionIndex] == null) {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            try {
                ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
                // 创建会话
                sessions[sessionIndex] = container.connectToServer(MyWebSocketClient.class, clientEndpointConfig, new URI(websocket));
                log.info("websocket 连接OK --> " + websocket);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    ;
                }
                return;
            }
        }
        if (!sessions[sessionIndex].isOpen()) {
            try {
                sessions[sessionIndex].close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            sessions[sessionIndex] = null;
            return;
        }
        Integer sentTimes;
        for (Integer eqid : LatestSensorStatusData.latestSensorStatusSend[sessionIndex].keySet()) {
            sentTimes = LatestSensorStatusData.latestSensorStatusSend[sessionIndex].get(eqid);

            if (sentTimes < 1) { // 正常情况下20秒一笔。足够时间发出去。不需要考虑同步
                List<SensorStatus> sensorStatuses = LatestSensorStatusData.latestSensorStatusData.get(eqid);
                if (sensorStatuses != null && !sensorStatuses.isEmpty()) {
                    try {
                        sessions[sessionIndex].getBasicRemote().sendText(JSON.toJSONString(sensorStatuses));
                        LatestSensorStatusData.latestSensorStatusSend[sessionIndex].put(eqid, sentTimes + 1);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        try {
                            sessions[sessionIndex].close();
                        } catch (Exception e2) {
                            e2.printStackTrace();
                            return;
                        }
                        sessions[sessionIndex] = null;
                    }
                }
            }
        }
    }

    // 每天晚上 12：30 写入一次数据库
    @Scheduled(cron="${data.write2dbcron}") // 每天 执行1次
    public void writeLatestSensorStatus2Db() {
        String queueTimesInfo = String.format("status:%d-%d-%d, sensor:%d-%d, control56:%d-%d-%d, elevator:%d-%d-%d, upload:%d-%d-%d, eqf: %d-%d-%d, eqf-dh: %d-%d-%d",
                QueueTimes.countData, QueueTimes.mqData, QueueTimes.tryData,
                QueueTimes.mqSensorData, QueueTimes.trySensorData,
                QueueTimes.count56, QueueTimes.mq56, QueueTimes.try56,
                QueueTimes.count56z, QueueTimes.mq56z, QueueTimes.try56z,
                QueueTimes.countUpload, QueueTimes.mqUpload, QueueTimes.tryUpload,
                QueueTimes.countEquipmentFault, QueueTimes.mqEquipmentFault,  QueueTimes.tryEquipmentFault,
                QueueTimes.countEquipmentFault_dh, QueueTimes.mqEquipmentFault_dh,  QueueTimes.tryEquipmentFault_dh);
        log.warn(queueTimesInfo);
        QueueTimes.clear();

        LatestSensorStatusData.latestSensorStatusData.forEach( (eqid, sensorStatuses) -> {
            if (sensorStatuses != null && !sensorStatuses.isEmpty()) {
                for (SensorStatus sensorStatus : sensorStatuses) {
                    if (latestSensorStatusMapper.update(sensorStatus) <= 0) {
                        latestSensorStatusMapper.insert(sensorStatus);
                    }
                }
            }
        });
    }

    //@Scheduled(initialDelay = 30000, fixedDelay = 60000)
    @Scheduled(initialDelay = 3000, fixedDelay = 6000)
    public void checkWeiBao() {
        // 只要超过 规定分钟数就算维保结束了
        if (MessageConsumer.isMaintainenceStatus == null || MessageConsumer.isMaintainenceStatus.isEmpty())
            return;

        MessageConsumer.isMaintainenceStatus.forEach((eqid, value) -> {
            if (
                    MessageConsumer.latestData_56Time.containsKey(eqid)
                &&  MessageConsumer.NormalTimeAterMaintainence.containsKey(eqid)
                &&  MessageConsumer.NormalTimeAterMaintainence2.containsKey(eqid)
                && (
                    MessageConsumer.NormalTimeAterMaintainence.get(eqid).isBefore(MessageConsumer.latestData_56Time.get(eqid))
                            || MessageConsumer.NormalTimeAterMaintainence2.get(eqid).isBefore(MessageConsumer.latestData_56Time.get(eqid))
                    )
            ) {
                log.info("leaving maintainence mode ..." + eqid);

                Equipment e1 = PublicVars.getEquipment(equipmentMapper,eqid);
                if (e1 != null) {

                    // maintainenceOffsetMinutes 分钟内是否有维保记录，如果有，合并
                    LocalDateTime thisStartTime = MessageConsumer.NormalTimeAterMaintainence2.get(eqid).minusMinutes(PublicVars.maintainenceCheckMinutes2);
                    LocalDateTime thisEndTime = MessageConsumer.NormalTimeAterMaintainence.get(eqid).isBefore(MessageConsumer.NormalTimeAterMaintainence2.get(eqid)) ?
                            MessageConsumer.NormalTimeAterMaintainence.get(eqid) : MessageConsumer.NormalTimeAterMaintainence2.get(eqid) ;

                    // SZ外网出现过 EndTime 小于 StartTime的情况 161911 2023-02-09 -- 02-26 有几笔 (内网OK的，可能与重启有关？)
                    LocalDateTime plus120m = thisStartTime.plusMinutes(PublicVars.maintainenceCheckMinutes2);
                    if (thisEndTime == null || thisStartTime.isAfter(thisEndTime) || plus120m.isBefore(thisEndTime)) {
                        thisEndTime = plus120m.isAfter(LocalDateTime.now()) && thisStartTime.isBefore(LocalDateTime.now())
                                ? LocalDateTime.now()
                                : plus120m;
                    }

                    // 上次结束 - 本次开始 一定时间内
                    List<Control56wb>  existWbs = control56wbMapper.getControl56wb(eqid, thisStartTime.minusMinutes(PublicVars.maintainenceOffsetMinutes));
                    if (existWbs != null && !existWbs.isEmpty()) {
                        // 合并到上一条。重算分钟数
                        Control56wb control56wb = existWbs.get(0);
                        if (control56wb.getTime().isBefore(thisEndTime)) {
                            control56wb.setEndtime(thisEndTime);
                            control56wb.setPeriod((int) Duration.between(control56wb.getTime(), control56wb.getEndtime()).toMinutes()); // 分钟数
                            // 这个无需发往队列，非客户端触发 control56wbMapper.update(control56wb);
                            for (int i = 0; i< sqltrytimes; i++) {
                                try {
                                    control56wbMapper.update(control56wb);
                                    break;
                                } catch (Exception ex) {
                                    log.error("{} error: {}", "control56wbMapper.update", ex.getMessage());
                                }
                                // 隔2秒再试
                                try {
                                    Thread.sleep(2000);
                                }catch (Exception ex2) {
                                    log.error("{} sleep error: {}", "control56wbMapper.update", ex2.getMessage());
                                }
                            }
                        }
                    } else {
                        // 180444没有56记录但是每天有几笔WB数据,见 2023-02-28 修改附件。
                        // 增加 维保合法性检查：期间内至少要有 4 笔记录，同时解决部分120分钟的问题(有时候尤其是晚上经常直接停机结束，不运行5分钟)，截止时间定为最后一笔 + 5分钟
                        List<Control56> control56s = control56Mapper.selectByEqIdAndBetweenTime(eqid, thisStartTime, thisEndTime);
                        if (control56s != null && !control56s.isEmpty() && control56s.size() >= PublicVars.wbNeedNumOfControl56s) {
                            Control56wb control56wb = new Control56wb();
                            control56wb.setLineid(e1.getLineid());
                            control56wb.setStationid(e1.getStationId());
                            control56wb.setEquipmentid(eqid);
                            control56wb.setTime(thisStartTime);
                            //LocalDateTime endTime = thisEndTime;
                            LocalDateTime endTime = control56s.get(control56s.size() - 1).getEndtime().plusMinutes(PublicVars.maintainenceCheckMinutes);
                            control56wb.setEndtime(endTime);
                            control56wb.setPeriod((int) Duration.between(control56wb.getTime(), control56wb.getEndtime()).toMinutes()); // 分钟数
//                    control56wb.setBk1(e1.getBk1());
//                    control56wb.setBk2(e1.getBk2());
//                    control56wb.setBk4(e1.getBk4());
//                    control56wb.setBk5(e1.getBk5());

                            // 这个无需发往队列，非客户端触发 control56wbMapper.insert(control56wb);
                            for (int i = 0; i< sqltrytimes; i++) {
                                try {
                                    control56wbMapper.insert(control56wb);
                                    break;
                                } catch (Exception ex) {
                                    log.error("{} error: {}", "control56wbMapper.insert", ex.getMessage());
                                }
                                // 隔2秒再试
                                try {
                                    Thread.sleep(2000);
                                }catch (Exception ex2) {
                                    log.error("{} sleep error: {}", "control56wbMapper.insert", ex2.getMessage());
                                }
                            }
                        }
                    }
                }
                MessageConsumer.isMaintainenceStatus.remove(eqid);
                MessageConsumer.NormalTimeAterMaintainence.remove(eqid);
                MessageConsumer.needResetTime4CheckMaintainence.remove(eqid);

                MessageConsumer.NormalTimeAterMaintainence2.remove(eqid);
                MessageConsumer.latestData_56Time.remove(eqid);
            }
        });

        // log.info("keeping maintainence mode ...");
    }

    //@Scheduled(initialDelay = 30000, fixedDelay = 60000)
    @Scheduled(initialDelay = 3000, fixedDelay = 5000)
    public void saveEnergy() {
        if (saveenergy != 1) {
            return;
        }
        if (connectionFactory == null) {
            connectionFactory = new ActiveMQConnectionFactory(activeMqConfig.getUrl(), activeMqConfig.getUser(), activeMqConfig.getPassword());
        }
        if (connection == null) {
            try {
                connection = connectionFactory.createConnection();
                connection.start();
            } catch (Exception ex) {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (Throwable e) {
                        // do nothing
                    }
                }
                connection = null;
                session = null;
                messageConsumer = null;
                ex.printStackTrace();
                return;
            }
        }

        if (messageConsumer == null) {
            try {
                session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
                Queue q = session.createQueue(QUEUE_ENERGY);
                messageConsumer = session.createConsumer(q);
            } catch (Exception ex) {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (Throwable e) {
                        // do nothing
                    }
                }
                connection = null;
                session = null;
                messageConsumer = null;
                ex.printStackTrace();
                return;
            }
        }

        Map<Integer, Consumeenergy> consumeenergyStationMap = new HashMap<>();


        while (1 > 0) {
            try {
                Message message = messageConsumer.receive(1L);

                if (message == null) {
                    if (!consumeenergyStationMap.isEmpty()) {
                        for (Integer stationid :
                                consumeenergyStationMap.keySet()) {
                            Consumeenergy e2 = consumeenergyStationMap.get(stationid);

                            if (consumeenergystationMapper.updateByEquipmentIdTime(e2) <= 0) {
                                e2.setStarttime(e2.getEndtime());
                                consumeenergystationMapper.insert(e2);
                            }
                        }
                        consumeenergyStationMap.clear();
                    }
                    break;
                }

                TextMessage objectMessage = (TextMessage) message;
                String data = objectMessage.getText();
                Consumeenergy e = JSON.parseObject(data, Consumeenergy.class);

                if (consumeenergyMapper.updateByEquipmentIdTime(e) <= 0) {
                    e.setStarttime(e.getEndtime());
                    consumeenergyMapper.insert(e);
                }

                Consumeenergy s = consumeenergyStationMap.get(e.getStationid());
                if (s != null) {
                    if (!s.getTime().equals(e.getTime())) {
                        // 同一车站时间不同，先保存旧的
                        if (consumeenergystationMapper.updateByEquipmentIdTime(s) <= 0) {
                            s.setStarttime(s.getEndtime());
                            consumeenergystationMapper.insert(s);
                        }
                        consumeenergyStationMap.remove(e.getStationid());
                        consumeenergyStationMap.put(e.getStationid(), e);
                    } else {
                        // 同车站同时间，先累加
                        s.setValue(s.getValue() + e.getValue());
                        if (e.getEndtime().isAfter(s.getEndtime()))
                            s.setEndtime(e.getEndtime());
                    }
                } else {
                    consumeenergyStationMap.put(e.getStationid(), e);
                }
            } catch (Exception ex) {
                if (!consumeenergyStationMap.isEmpty()) {
                    for (Integer stationid :
                            consumeenergyStationMap.keySet()) {
                        Consumeenergy e2 = consumeenergyStationMap.get(stationid);

                        if (consumeenergystationMapper.updateByEquipmentIdTime(e2) <= 0) {
                            e2.setStarttime(e2.getEndtime());
                            consumeenergystationMapper.insert(e2);
                        }
                    }
                    consumeenergyStationMap.clear();
                }
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (Throwable e) {
                        // do nothing
                    }
                }
                connection = null;
                session = null;
                messageConsumer = null;
                ex.printStackTrace();
                return;
            }
        }
    }

    public void send2WebSocket_Fault2Email(LocalDateTime wsTime, int sessionIndex, String websocket) {
        if (websocket == null || websocket.isEmpty()) {
            return;
        }

        if (sessions[sessionIndex] == null) {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            try {
                ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
                // 创建会话
                sessions[sessionIndex] = container.connectToServer(MyWebSocketClient.class, clientEndpointConfig, new URI(websocket));
                log.info("websocket 连接OK --> " + websocket);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    ;
                }
                return;
            }
        }
        if (!sessions[sessionIndex].isOpen()) {
            try {
                sessions[sessionIndex].close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            sessions[sessionIndex] = null;
            return;
        }

        while (true) {
            if (EmailDatalList.emailDatas.isEmpty()) {
                break;
            }
            EmailData emailData = EmailDatalList.emailDatas.get(0);

            try {
                sessions[sessionIndex].getBasicRemote().sendText(JSON.toJSONString(emailData));
                EmailDatalList.emailDatas.removeElementAt(0);
                log.info("sent a email data to portal : {}", emailData);
            } catch (Exception ex) {
                ex.printStackTrace();
                try {
                    sessions[sessionIndex].close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                    return;
                }
                sessions[sessionIndex] = null;
            }
        }
    }

    @Scheduled(cron="0 10 0 * * ?") // 清理56旧状态。否则有可能一直不变例如一直停梯的第二天不写入
    public void dailyInit2() {
        MessageConsumer.lastControl56s.clear();
        MessageConsumer.lastElevators.clear();
    }

    @Scheduled(initialDelay = 10000, fixedDelay = 10)
    public void setTodayAndNextDay() {
        if (PublicVarsTimeDay.running2StopEquipmentStatus != null && !PublicVarsTimeDay.running2StopEquipmentStatus.isEmpty()) {
            EquipmentStatus equipmentStatus = PublicVarsTimeDay.running2StopEquipmentStatus.get(0);
            PublicVarsTimeDay.saveEquipmentStatusThisMonth(equipmentStatus, equipmentStatusThisMonthMapper, equipmentStatusTodayMapper, equipmentStatusAlldayMapper, equipmentMapper);
            PublicVarsTimeDay.running2StopEquipmentStatus.remove(0);
        }
        if (saveTimeCount >= 1000) {
            PublicVarsTimeDay.checkTodayAndNextDay();
            saveTimeCount = 0;
        }
        saveTimeCount++;
    }
}
